package com.spring.theory.aop.jdkProxy;

import com.spring.theory.aop.jdkProxy.TestJdkProxy.InvokeHandler;
import com.spring.theory.aop.jdkProxy.TestJdkProxy.TestInterface;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * $Proxy 代理类
 * -jdk代理类模仿实现
 * <p>
 * 基于接口的动态代理实现
 * 可以继承Proxy类；里面提供了InvokeHandler对象及构造方法；不用手动创建构造 InvocationHandler
 */
public class $ProxyTest implements TestInterface {

    /**
     * 接口成员变量，实际的处理逻辑由外部调用者处实现
     */
    private InvokeHandler handler;

    public $ProxyTest(InvokeHandler handler) {
        this.handler = handler;
    }

    /**
     * 基于接口的代理；每个方法都需要重写
     */
    @Override
    public void test() {
        try {
            /**
             * 方法对象获取只需要一次调用；初始化在静态代码块中
             * 在代理中invoke，代理对象就是它本身
             */
            //Method method = TestInterface.class.getMethod("test");
            handler.invoke(this, test, new Object[0]);
        } catch (RuntimeException | Error e) {
            //运行时异常直接抛出
            throw e;
        } catch (Throwable e) {
            //检查异常 转换后抛出
            throw new RuntimeException(e);
            //throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public int test2() {
        try {
            return (int) handler.invoke(this, test2, new Object[0]);
        } catch (RuntimeException | Error e) {
            throw e;
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    static Method test;
    static Method test2;

    static {
        try {
            test = TestInterface.class.getMethod("test");
            test2 = TestInterface.class.getMethod("test2");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }
}
